#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <string.h>
#include "parse.h"
#include "buffer.h"
#include "response.h"
#include <sys/select.h>


#define LISO_PORT 9999
#define BUF_SIZE 4096*4 
#define MAXFDS 1024

#define SELECT  //select并发开关


int sock = -1; //服务器监听套接字
char buf[BUF_SIZE]; //暂存接收数据的缓冲区

//连接状态结构体
typedef struct {
    Buffer buffer;
    struct sockaddr_in addr;
} ClientInfo;

int close_socket(int socket); 
void close_connection(int sockfd, fd_set *all_fd, int *max_fd, int server_sock, ClientInfo *clients);

int main(int argc, char *argv[]) {
    socklen_t cli_size;
    struct sockaddr_in addr, cli_addr;
    printf("----- Liso Server -----\n");

    if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
        printf("Failed creating socket.\n");
        return EXIT_FAILURE;
    }

    addr.sin_family = AF_INET; // ipv4
    addr.sin_port = htons(LISO_PORT);
    addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(sock, (struct sockaddr *) &addr, sizeof(addr))) {
        close_socket(sock);
        printf("Failed binding socket.\n");
        return EXIT_FAILURE;
    }

    if (listen(sock, 5)) {
        close_socket(sock);
        printf("Error listening on socket.\n");
        return EXIT_FAILURE;
    }

    #ifndef SELECT
    Buffer bf_recv; //请求接收缓冲区
    buffer_init(&bf_recv);
    int readret = 0;
    while((readret = recv(cli_sock,buf,BUF_SIZE,0)) >= 1){ 
        buf[readret] = '\0'; //显式加上结束符，保证安全
        buffer_append(&bf_recv,buf,readret);//接收客户端数据到缓冲区
        printf("Received (total %d bytes) messages:\n",readret); 
        printf("---------------------------------------------\n");
        printf("%s ",bf_recv.data); 
        printf("---------------------------------------------\n");
        
        bool isPersistent;
        char* start = bf_recv.data;//指向当前处理的起始位置
        char *end;//指向 \r\n\r\n 分隔符
        //用strstr搜索\r\n\r\n，返回其位置
        while((end = strstr(start, "\r\n\r\n")) != NULL) {
            //当前请求的数据，从 start 到 end + 4
            int buf_len = end + 4 - start;
            Buffer bf;
            buffer_init(&bf);
            buffer_append(&bf, start, buf_len);
            
            //解析并处理请求
            isPersistent = parseRequest(&bf,&cli_addr,cli_sock);
            //释放bf
            buffer_free(&bf);
            //检查是否是keep alive
            if(!isPersistent) break;
            start += buf_len;
        }

            if(!isPersistent) break;

            memset(buf, 0, BUF_SIZE);
        }

        buffer_free(&bf_recv);

        if (close_socket(cli_sock)){
            close_socket(sock);
            printf("Error closing client socket.\n");
            return EXIT_FAILURE;
        }
        printf("Closed connection from %s:%d\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));
    }
    #endif

    #ifdef SELECT //select实现并发
    fd_set all_fd, read_fds;
    FD_ZERO(&all_fd);
    FD_SET(sock, &all_fd);
    int max_fd = sock; //max_fd存储当前所有socket中的max
    
    ClientInfo clients[MAXFDS]; //所有客户端信息

    while(1) {
        read_fds = all_fd; 
        printf("Waiting for connection...\n");
        if(select(max_fd + 1, &read_fds, NULL, NULL, NULL) == -1) {
            printf("Select Error.\n");
            return EXIT_FAILURE;
        }

        for(int i = 0; i <= max_fd; i++){
            if(!FD_ISSET(i, &read_fds)) continue;

            if(i == sock) { //监听到新连接
                cli_size = sizeof(cli_addr);
                int cli_sock = accept(sock, (struct sockaddr *) &cli_addr, &cli_size);
                if(cli_sock == -1){
                    printf("Accept Error.\n");
                    continue; //不退出，继续处理其他连接
                }
                
                if(cli_sock >= MAXFDS){ //数量限制
                    printf("Clients full\n");
                    close(cli_sock);
                } 
                else{ //记录客户端信息
                    clients[cli_sock].addr = cli_addr;
                    buffer_init(&clients[cli_sock].buffer);
                    
                    FD_SET(cli_sock, &all_fd);
                    //尝试更新max_fd
                    if(cli_sock > max_fd) max_fd = cli_sock; 
                    
                    printf("New connection from %s:%d\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));
                }
            } 
            else{ //处理客户端数据
                int cli_sock = i;
                ClientInfo *client = &clients[cli_sock];
                int readret;
                
                char buf[BUF_SIZE]; //临时缓冲区
                readret = recv(cli_sock, buf, BUF_SIZE, 0);
                if(readret == 0){ //客户端关闭
                    printf("Client %s:%d closed connection\n",inet_ntoa(client->addr.sin_addr), ntohs(client->addr.sin_port));
                    close_connection(cli_sock, &all_fd, &max_fd, sock, clients);
                } 
                else if(readret < 0){ //读取错误
                    printf("recv error\n");
                    close_connection(cli_sock, &all_fd, &max_fd, sock, clients);
                } 
                else{ //有数据需要处理
                    //追加到客户端缓冲区
                    buffer_append(&client->buffer, buf, readret);

                    printf("Received %d bytes from %s:%d\n", readret,inet_ntoa(client->addr.sin_addr), ntohs(client->addr.sin_port));
                    printf("---------------------------------------------\n");
                    printf("%s ",client->buffer.data); 
                    printf("---------------------------------------------\n");
                    
                    bool isPersistent;
                    char* start = client->buffer.data;
                    char *end;
                    while((end = strstr(start, "\r\n\r\n")) != NULL) {
                        //当前请求的数据，从 start 到 end + 4
                        int buf_len = end + 4 - start;
                        Buffer bf;
                        buffer_init(&bf);
                        buffer_append(&bf, start, buf_len);
                        
                        //解析并处理请求
                        isPersistent = parseRequest(&bf,&cli_addr,cli_sock);
                        //释放bf
                        buffer_free(&bf);
                        //检查是否是keep alive
                        if(!isPersistent) break;
                        start += buf_len;
                    }
            
                    if(!isPersistent) close_connection(cli_sock, &all_fd, &max_fd, sock, clients);
                        memset(buf, 0, BUF_SIZE);
                
                    //清空缓冲区
                    buffer_clear(&client->buffer);
            
                }
            }
        }
    }
    #endif

    
    close_socket(sock);
    return EXIT_SUCCESS;
}


int close_socket(int socket) {
    if (close(socket)) {
        fprintf(stderr, "Failed closing socket.\n");
        return 1;
    }
    return 0;
}

void close_connection(int sockfd, fd_set *all_fd, int *max_fd, int server_sock, ClientInfo *clients) {
    close(sockfd);
    FD_CLR(sockfd, all_fd);
    buffer_free(&clients[sockfd].buffer);
    
    //更新max_fd
    if(sockfd == *max_fd) {
        while(*max_fd >= server_sock && !FD_ISSET(*max_fd, all_fd))
            (*max_fd)--;
    }
    
    printf("Closed connection from %s:%d\n",inet_ntoa(clients[sockfd].addr.sin_addr), ntohs(clients[sockfd].addr.sin_port));
}






